package com.geekbang.work.lock;

import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;

import java.util.concurrent.locks.Lock;

/**
 * @author nhsoft.lul
 */
@Data
@SpringBootApplication
public class RedisLockApplication implements CommandLineRunner {
    public static void main(final String args[]) {
        SpringApplication.run(RedisLockApplication.class, args);
    }

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    private RedisLockRegistry redisLockRegistry;


    @Override
    public void run(String... args) throws Exception {
        RedisLockRegistry redisLockRegistry = new RedisLockRegistry(redisConnectionFactory, "REDIS_LOCK");
        Runnable runnable1 = () -> {
            RedisLockApplication demo = new RedisLockApplication();
            demo.setRedisLockRegistry(redisLockRegistry);
            Lock lock = demo.lock("lock");
            if( lock.tryLock()){
                System.out.println("d1获取锁");
                demo.service(lock);
            }else{
                System.out.println("d1获取锁失败");
            }
        };
        Runnable runnable2 = () -> {
            RedisLockApplication demo = new RedisLockApplication();
            demo.setRedisLockRegistry(redisLockRegistry);
            Lock lock = demo.lock("lock");
            if( lock.tryLock()){
                System.out.println("d2获取锁");
                demo.service(lock);
            }else{
                System.out.println("d2获取锁失败");
            }
        };
        new Thread(runnable1).start();
        new Thread(runnable2).start();
    }

    public Lock lock(String key) {
        Lock lock = redisLockRegistry.obtain(key);
        return lock;
    }

    public void release(final Lock lock) {
        if (lock == null) {
            return;
        }
        try {
            lock.unlock();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void service(Lock lock) {
        //模拟业务处理
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            release(lock);
        }
    }
}
